Previous Book Contents Book Index Next

Inside Macintosh: Overview /
Chapter 8 - Menus


Handling Menu Choices

Your application is informed of user menu choices in a slightly roundabout fashion. First, your application receives a mouse-down event indicating that the user has clicked in the menu bar. At that time, you should call the Menu Manager function MenuSelect to determine which menu and menu item, if any, the user chose. When you call MenuSelect, the Menu Manager pulls down the appropriate menu and tracks all subsequent mouse movement in the menu. When the user releases the mouse button, MenuSelect exits and returns to your application a long integer that indicates which menu and item the user chose. The high-order word of that long integer contains the menu number, and the low-order word contains the menu item number.

To coordinate the menu numbers and menu item numbers with the menus and menu items as defined in your 'MBAR' and 'MENU' resources, you'll probably want to define a set of constants, as shown in Listing 8-2.

Listing 8-2 Defining menu numbers and menu item numbers

CONST
   mApple         = 128;            {resource ID of Apple menu}
   iAbout         = 1;              {our About... dialog}

   mFile          = 129;            {resource ID of File menu}
   iNew           = 1;
   iClose         = 2;
   iQuit          = 4;

   mEdit          = 130;            {resource ID of Edit menu}
   iUndo          = 1;
   iCut           = 3;
   iCopy          = 4;
   iPaste         = 5;
   iClear         = 6;

   mVenn          = 131;            {resource ID of Venn menu}
   iCheckVenn     = 1;
   iDoVenn        = 2;
   iClearVenn     = 3;
   iNextTask      = 4;
   iCheckArg      = 5;
   iGetVennPrefs  = 7;
Note
The divider in a menu counts as a menu item, even though the user can't choose it.
In general, you'll define a routine like DoMenuCommand shown in Listing 8-3 to handle all menu choices. Both your mouse-down event handler (Listing 6-9 on page 121) and your key-down event handler (Listing 8-5 on page 160) call MenuSelect. It is passed either the result of MenuSelect (for menu selections) or MenuKey (for keyboard equivalents of menu selections).

Listing 8-3 Handling menu selections

PROCEDURE DoMenuCommand (menuAndItem: LongInt);
   VAR
      myMenuNum:  Integer;
      myItemNum:  Integer;
      myResult:   Integer;
      myDAName:   Str255;
      myWindow:   WindowPtr;
BEGIN
   myMenuNum := HiWord(menuAndItem);
   myItemNum := LoWord(menuAndItem);
   GetPort(myWindow);

   CASE myMenuNum OF
      mApple: 
         CASE myItemNum OF
            iAbout: 
               BEGIN
                  DoAboutBox;
               END;
            OTHERWISE
               BEGIN
                  GetMenuItemText(GetMenuHandle(mApple), myItemNum,
                                     myDAName);
                  myResult := OpenDeskAcc(myDAName);
               END;
         END;
      mFile: 
         BEGIN
            CASE myItemNum OF
               iNew: 
                  myWindow := DoCreateWindow;
               iClose: 
                  DoCloseWindow(FrontWindow);
               iQuit: 
                  DoQuit;
               OTHERWISE
                  ;
            END;
         END;
      mEdit:
         BEGIN
            IF NOT SystemEdit(myItemNum - 1) THEN
               ;
         END;
      mVennD: 
         BEGIN
            myWindow := FrontWindow;
            CASE myItemNum OF
               iCheckVenn: 
                  DoVennCheck(myWindow);
               iDoVenn: 
                  DoVennAnswer(myWindow);
               iClearVenn: 
                  DoVennClear(myWindow);
               iNextTask: 
                  DoVennNext(myWindow);
               iCheckArg: 
                  DoVennAssess(myWindow);
               iGetVennPrefs: 
                  DoModelessDialog(rVennDPrefsDial, gPrefsDialog);
               OTHERWISE
                  ;
            END;
         END;

      OTHERWISE
         ;
   END;
   HiliteMenu(0);
END;
The DoMenuCommand procedure is passed a long integer that encodes the menu number and item number of the chosen item. As you can see, DoMenuCommand consists mainly of a CASE statement that branches on the menu number. Each menu number, in turn, consists mainly of a CASE statement that branches on the menu item number. In this simple way, you can handle all menus and all menu items.

Most of the innermost branches just call application-defined routines to handle the appropriate menu item choice. (For example, if the user chooses Quit from the File menu, then DoMenuCommand calls the application-defined routine DoQuit.) The code that handles choices in the Apple menu (Listing 8-4) is slightly different, however.

Listing 8-4 Handling Apple menu selections

iAbout: 
   BEGIN
      DoAboutBox;
   END;
OTHERWISE
   BEGIN
      GetMenuItemText(GetMenuHandle(mApple), myItemNum, myDAName);
      myResult := OpenDeskAcc(myDAName);
   END;
If the user chooses the command About Venn Diagrammer (picked out by the constant iAbout), then DoMenuCommand calls the application-defined routine DoAboutBox (see Listing 7-7 on page 145). Otherwise, the user must have chosen a desk accessory or other item in the Apple menu. In that case, DoMenuCommand retrieves the name of the desk accessory (by calling GetMenuItemText) and passes that name to the OpenDeskAcc function.

Because Venn Diagrammer doesn't support any text editing, it simply calls the system software routine SystemEdit to handle user choices in the Edit menu. SystemEdit checks whether the frontmost window belongs to a desk accessory; if so, it passes the menu choice to the desk accessory and returns TRUE. The parameter to SystemEdit is interpreted so you can pass the item number less 1 of the standard Edit menu commands.

Before exiting, DoMenuCommand calls the Menu Manager procedure HiliteMenu to undo the menu title highlighting provided automatically by MenuSelect or MenuKey.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
9 JUL 1996